/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sg.edu.nus.iss.pacman.net.bluetooth.client;

import sg.edu.nus.iss.pacman.net.bluetooth.*;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;

/**
 * This class performs all the operations for the bluetooth client.
 * @author fredy
 */
public class BluetoothClient
{
    private LocalDevice localDevice;
    private boolean interrupted;
    public static final int MODE_SEARCH_DEVICE = 0;
    public static final int MODE_SEND_MESSAGE = 1;
    private static final String BLUETOOTH_PROTOCOL = "btspp://";
    private static final String CONNECTION_STRING =
        ":1;master=false;encrypt=false;authenticate=false";
    private BluetoothClientListener listener;

    /**
     * Creates a new instance of BluetoothClient.
     * @param listener the BluetoothClientListener
     */
    public BluetoothClient(BluetoothClientListener listener)
    {
        this.listener = listener;
        try
        {
            localDevice = LocalDevice.getLocalDevice();
        }
        catch (BluetoothStateException ex)
        {
            ex.printStackTrace();
            new RuntimeException(ex.getMessage());
        }
    }

    /**
     * Check if the sending the message is interrupted.
     * @return true if it's interrupted; false otherwise
     */
    public boolean isInterrupted()
    {
        return interrupted;
    }

    /**
     * Interrupts sending the message.
     */
    public void interrupt()
    {
        this.interrupted = true;
    }

    class SearchRemoteDevicesRunnable implements Runnable
    {
        private BluetoothDevice[] bluetoothDevices;

        public void run()
        {
            search();
        }

        private void search()
        {
            try
            {
                Vector remoteDevices = new Vector();
                DiscoveryAgent agent = localDevice.getDiscoveryAgent();
                ClientDiscoveryListener listener = new ClientDiscoveryListener(remoteDevices);
                agent.startInquiry(DiscoveryAgent.GIAC, listener);
                while (!isInterrupted() &&
                    listener.getStatus() != ClientDiscoveryListener.STATUS_INQUIRY_COMPLETED)
                {
//                    System.out.println("Waiting...");
                }

                bluetoothDevices = new BluetoothDevice[remoteDevices.size()];
                for (int i = 0; i < remoteDevices.size(); i++)
                {
                    RemoteDevice remoteDevice = (RemoteDevice) remoteDevices.elementAt(i);
                    BluetoothDevice bluetoothDevice = new BluetoothDevice();
                    bluetoothDevice.setBluetoothAddress(remoteDevice.getBluetoothAddress());
                    bluetoothDevice.setFriendlyName(remoteDevice.getFriendlyName(true));
                    bluetoothDevices[i] = bluetoothDevice;
                }
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
                throw new RuntimeException(ex.getMessage());
            }
            listener.found(bluetoothDevices);
        }
    }

    class SendMessageRunnable implements Runnable
    {
        private BluetoothDevice bluetoothDevice;
        private String message;

        public SendMessageRunnable(BluetoothDevice bluetoothDevice, String message)
        {
            this.bluetoothDevice = bluetoothDevice;
            this.message = message;
        }

        public void run()
        {
            send();
        }

        private void send()
        {
            System.out.println("send");
            byte[] msgByte = message.getBytes();
            StringBuffer url = new StringBuffer();
            url.append(BLUETOOTH_PROTOCOL);
            url.append(bluetoothDevice.getBluetoothAddress());
            url.append(CONNECTION_STRING);
            System.out.println("URL: " + url.toString());

            StreamConnection conn = null;
            OutputStream os = null;
            try
            {
                conn = (StreamConnection) Connector.open(url.toString());
                os = conn.openOutputStream();
                os.write(msgByte);
                os.flush();
                listener.sent();
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
                throw new RuntimeException(ex.getMessage());
            }
            finally
            {
                try
                {
                    if (os != null)
                    {
                        os.close();
                    }
                    if (conn != null)
                    {
                        conn.close();
                    }
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                    throw new RuntimeException(ex.getMessage());
                }
            }
        }
    }

    /**
     * Sends the message. This method doesn't block.
     * @param device the bluetooth device
     * @param message the message
     */
    public void sendMessage(BluetoothDevice device, String message)
    {
        Thread t = new Thread(new SendMessageRunnable(device, message));
        t.start();
    }

    /**
     * Search the remote devices. This method doesn't block.
     */
    public void searchRemoteDevices()
    {
        interrupted = false;
        Thread t = new Thread(new SearchRemoteDevicesRunnable());
        t.start();
    }
}
